home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / mailsr / popmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-26  |  28.3 KB  |  1,321 lines

  1. #define noDEBUG
  2. #define CAPTURE
  3. #define noLISTCAPTURE
  4. /*
  5.  * Written March 25, 1992 Hans Wieser
  6.  *
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <tos.h>
  13. #include <time.h>
  14. #include <ext.h>
  15. #include "ownfunc.h"
  16. #include "cookie.h"
  17. #include "inetcust.h"
  18. #include "mailrc.h"
  19.  
  20. #ifndef FALSE
  21. #define FALSE 0
  22. #define TRUE !FALSE
  23. #endif
  24.  
  25. int loop;
  26. int pop_ctl;
  27. unsigned char *pop_cmdbuf;
  28. int pop_cmdbufi;
  29. FILE *fo = NULL;
  30. FILE *fi = NULL;
  31.  
  32. FILE *pop_log = NULL;
  33.  
  34. #define POP_OK "+OK"
  35. #define POP_ERR "-ERR"
  36. #define PROMPT "PopMail> "
  37. #define POPMAILPORT    110
  38. #define BEE    2
  39. #define MORE "\033pmore...\033q"
  40. long        POP_BUFFERSIZE = 8192L;
  41.  
  42.  
  43. char *myid = "@(#)ANS-PopMail Client 1.4 by hw";
  44.  
  45. char pop_userstr[2000];    /* string typed in by user */
  46.  
  47. char pop_linefrom[30];
  48. char pop_linedate[16];
  49. char pop_linesubj[32];
  50. char pop_linestat[4];
  51. int pop_ListCnt;
  52.  
  53. char *pop_argv[10];
  54. int  pop_argc;
  55.  
  56. char username[20];
  57. char hostname[20];
  58.  
  59. char curpath[128];
  60.  
  61. char pop_mailto[2000];
  62. char pop_mailfile[128];
  63. char pop_mailsubj[128];
  64. int pop_maxdisk;
  65. int pop_getok;
  66. int pop_connect;
  67.  
  68. typedef struct
  69. {
  70.     char *cmd;
  71.     int     (*pop_fn)(int,int,char **);
  72.     char *help;
  73. } pop_cmd;
  74.  
  75. void popmail(char *,char *,char *);
  76. int pop_dispatch(int,char *);
  77. int pop_help(int, int, char **);
  78. int pop_list(int, int, char **);
  79. int pop_retr(int, int, char **);
  80. int pop_get(int, int, char **);
  81. int pop_mget(int, int, char **);
  82. int pop_exit(int, int, char **);
  83. int pop_dummy(int, int, char **);
  84. int pop_stat(int, int, char **);
  85. int pop_rset(int, int, char **);
  86. int pop_mail(int, int, char **);
  87. int pop_alias(int, int, char **);
  88. int pop_cd(int, int, char **);
  89. int pop_del (int, int, char **);
  90.  
  91. int nconnect(char *host, unsigned int port);
  92.  
  93. int nputc(int s, char c);
  94. int nputs(int s, char *str);
  95. int nputl(int s, char *str);
  96. char *ngets(int s, char *str, size_t len);
  97. int ngetc(int s);
  98. int navail(int s);
  99. int nprintf(int,char *,...);
  100. int ncapture(char *);
  101.  
  102. pop_cmd cmd_tab[] = 
  103. {
  104.     { "?"    , pop_help    ,"?     [cmd]   print help, cmd may be abbreviated"},
  105.     { "help", pop_help    ,"help  [cmd]   print help, cmd may be abbreviated"},
  106.     { "alias",pop_alias ,"alias name        show the long version of \"name\""},
  107.     { "cd"   ,pop_cd    ,"cd [[d:]dir]      change local directory"},
  108.     { "del" , pop_del   ,"del msgs      delete messages,\r\n"
  109.                          "              msgs is a list or a range of messages\r\n"
  110.                          "              \"2,5\"  message 2 and message 5\r\n"
  111.                          "              \"2-5\"  all messages from 2 up to 5\r\n"
  112.                          "              \" -5\"  all messages from first up to 5\r\n"
  113.                          "              \"2-\"   all messages from 2 up to last\r\n"
  114.                          "              \"-\"    all messages"  },
  115.     { "exit", pop_exit  ,"exit              finish work undoing all deletings of this session "},
  116.     { "get" , pop_get   ,"get msgno file    copy message to local file "},
  117.     { "quit", pop_dummy    ,"quit          finish work saving new maildropstate"},
  118.     { "list", pop_list  ,"list          get a list of all messages"},
  119.     { "mail", pop_mail  ,"mail [to [file]]  send a message\r\n"
  120.                          "                  \"to\" is the recipient of the message\r\n"
  121.                          "                  and can be a alias from file mailrc.*\r\n"
  122.                          "                  if the filename is omitted, you have to type in the message"},
  123.     { "mget" , pop_mget ,"mget msgs file.nr    copy multiple messages,\r\n"
  124.                          "                     file is a part of the filename, '.nr' will be appended\r\n"
  125.                          "                     msgs is a list or a range of messages\r\n"
  126.                          "                     \"2,5\"  message 2 and message 5\r\n"
  127.                          "                     \"2-5\"  all messages from 2 up to 5\r\n"
  128.                          "                     \" -5\"  all messages from first up to 5\r\n"
  129.                          "                     \"2-\"   all messages from 2 up to last\r\n"
  130.                          "                     \"-\"    all messages"  },
  131.     { "retr", pop_retr  ,"[retr] msgno  retrieve a message,\r\n"
  132.                          "              keyword retr may be omitted"},
  133.     { "rset", pop_rset  ,"rset          undelete all in this session deleted messages"},
  134.     { "stat", pop_stat  ,"stat          show number of available messages"},
  135.     { NULL  , NULL      }
  136. };
  137.  
  138. void pop_quit(int);
  139. int pop_getresponse(int s,char *str,size_t len,int echo);
  140. int pop_login(int s,char *str,size_t len);
  141. int pop_getcmd(char *,char *,size_t,int);
  142. int pop_args(char *str,char *argv[]);
  143. int pop_printf(char *,...);
  144.  
  145.  
  146. main(int argc, char **argv)
  147. {
  148.   char *hostname;
  149.   char rcv[40],mailfile[128];
  150.   COOKIE *cookie;
  151.   INETCUST *custom;
  152.   
  153.   cookie = get_cookie(INETCUSTCOOKIE);
  154.   if(!cookie || (custom = (INETCUST *)(cookie->val)) == NULL)
  155.   {
  156.       printf("INETCUST not loaded!\n<CR>");
  157.       Cconin();
  158.       exit(1);
  159.   }
  160.  
  161.   hostname = custom->mailhost;
  162.   if(strlen(hostname) == 0) hostname = "xx";
  163.   Cursconf(0,0);
  164.   printf("\033E\033v");
  165.   Cursconf(1,0);
  166.   mailfile[0] = 0;
  167.   rcv[0] = 0;
  168.  
  169.   if(argc >3)
  170.   {
  171.     printf("popmail [recipient [file]]\n<CR>");
  172.     Cconin();
  173.     exit(1);
  174.   }
  175.   printf("ANS-PopMail Client 1.4  (c) 1992 hw\n");
  176.   printf("connecting to host %s\n\n",hostname);
  177.   if(argc >= 2)
  178.   {
  179.     strncpy(rcv,argv[1],sizeof(rcv));
  180.     rcv[sizeof(rcv) -1] = 0;
  181.   }
  182.   if(argc == 3)
  183.   {
  184.     strncpy(mailfile,argv[2],sizeof(mailfile));
  185.     mailfile[sizeof(mailfile) -1] = 0;
  186.   }
  187.   popmail(hostname,rcv,mailfile);
  188.   return 0;
  189. }
  190.  
  191.  
  192.  
  193. void popmail(char *hostnm,char *mailto,char *mailfile)
  194. {
  195.   int pop_abort;
  196.   long pop_wnd;
  197.  
  198.   /* set up state variables */
  199.   strcpy(hostname,hostnm);
  200.   strcpy(pop_mailto,mailto);
  201.   strcpy(pop_mailfile,mailfile);
  202.   
  203.   if(getenv("POPLOG"))
  204.   {
  205.       pop_log = fopen((char *)getenv("POPLOG"),"wb");
  206.   }
  207.   
  208.   if(getenv("TCPWND"))
  209.   {
  210.     pop_wnd = atol((const char *)getenv("TCPWND"));
  211.     if(pop_wnd) POP_BUFFERSIZE = pop_wnd;
  212.   }
  213.   getcwd(curpath,(int)sizeof(curpath)-1);
  214.  
  215.   pop_printf("\033v");
  216.   
  217.   pop_ctl = nconnect(hostnm,POPMAILPORT);
  218.   if(pop_ctl <= 0) 
  219.   {
  220.       switch(pop_ctl)
  221.       {
  222.           case 0:
  223.             pop_printf("mailhost '%s' unknown\r\n",hostnm);
  224.             break;
  225.           case -1:
  226.             pop_printf("out of buffers to build connection\r\n");
  227.             break;
  228.           case -2:
  229.             pop_printf("connection refused\r\n",hostnm);
  230.             break;
  231.     }
  232.     pop_printf("<CR>");
  233.     Crawcin();
  234.       return;
  235.   }
  236.   pop_connect = TRUE;
  237.   if(!pop_getresponse(pop_ctl,pop_userstr,sizeof(pop_userstr),FALSE))
  238.   {
  239.       tcp_abort(pop_ctl);
  240.       return;
  241.   }
  242.   if(!pop_login(pop_ctl,pop_userstr,sizeof(pop_userstr)))
  243.   {
  244.     pop_quit(pop_ctl);
  245.     pop_printf("<CR>");
  246.     Crawcin();
  247.     return;
  248.   }
  249.   if(pop_mailto[0])
  250.   {
  251.       pop_argv[0] = "mail";
  252.       pop_argv[1] = pop_mailto;
  253.       pop_argc = 2;
  254.       if(pop_mailfile[0])
  255.       {
  256.           pop_argc++;
  257.           pop_argv[2] = pop_mailfile;
  258.       }
  259.       pop_mail(pop_ctl,pop_argc,pop_argv);
  260.       pop_abort = '\n';
  261.   }
  262.   else
  263.       while(pop_connect >= 0 && (pop_abort = pop_getcmd(PROMPT,pop_userstr,sizeof(pop_userstr),TRUE)) == '\n')
  264.       {
  265.         if(!pop_dispatch(pop_ctl,pop_userstr)) break;
  266.       }
  267.   if(pop_connect>=0 && pop_abort)
  268.   {
  269.       if(pop_abort != '\n') pop_exit(pop_ctl,0,NULL);
  270.       pop_quit(pop_ctl);
  271.   }
  272.   if(pop_log) fclose(pop_log);
  273.   
  274. }
  275.  
  276. int pop_args(char *str,char *argv[])
  277. {
  278. register int argc = 0;
  279.     do
  280.     {
  281.         while(*str && (*str == ' ' || *str == '\t')) str++;
  282.         if(*str)
  283.         {
  284.             argv[argc] = str;
  285.             argc++;
  286.         }
  287.         while(*str && !(*str == ' ' || *str == '\t')) str++;
  288.         if(!*str) break;
  289.         *str++ = 0;            /* cut string into single words */
  290.     } while(argc <= 10);
  291.     if(argc < 10) argv[argc] = NULL;
  292.     return(argc);
  293. }
  294.  
  295.  
  296. int pop_login(int s,char *str,size_t len)
  297. {
  298.   do
  299.   {
  300.     if(pop_getcmd("user: ",str,len,TRUE) != '\n')
  301.         return(FALSE);
  302.     strncpy(username,str,sizeof(username));
  303.       nprintf(s,"user %s\r\n",str);
  304.   } while(!pop_getresponse(s,str,len,FALSE));
  305.  
  306.   if(pop_getcmd("Password: ",str,len,FALSE) != '\n')
  307.     return(FALSE);
  308.   nprintf(s,"pass %s\r\n",str);
  309.   if(!pop_getresponse(s,str,len,TRUE))
  310.       return(FALSE);
  311.   return(TRUE);        /* now we logged in */
  312. }
  313.  
  314. void pop_quit(int s)
  315. {
  316. char buf[80];
  317.       nputl(s,"quit");
  318.       pop_getresponse(s,buf,sizeof(buf)-1,FALSE);
  319.       tcp_close(s);
  320.     return;
  321. }
  322.  
  323.  
  324. int pop_getresponse(int s,char *str,size_t len,int echo)
  325. {
  326. long timeout = 0;
  327. int    seq = 0;
  328.  
  329.     if(echo == BEE)
  330.     {
  331.         while(pop_connect >= 0 && !navail(s))
  332.             if(clock() > timeout)
  333.             {
  334.                 pop_printf("\r%c","-\\|/"[seq++ % 4]);
  335.                 timeout = clock()+50;
  336.             }
  337.             pop_printf("\r \r");
  338.     }
  339.     ngets(s,str,len);
  340.     if(pop_connect < 0) return(FALSE);
  341.     if(echo && (*str == POP_OK[0] || *str == POP_ERR[0]))
  342.         pop_printf("%s\r\n",str+1);
  343.     if(!strncmp(str,POP_OK,strlen(POP_OK))) return(TRUE);
  344.     return(FALSE);
  345. }
  346.     
  347.  
  348.  
  349. int pop_getcmd(char *prompt,char *cmd, size_t len,int echo)
  350. {
  351. register char c;
  352. register size_t i;
  353.  
  354.     i=0;
  355.     cmd[i] = 0;
  356.     pop_printf("\r%s",prompt);
  357.     while(i < len)
  358.     {
  359.         if(Cconis()) switch(c = (char)Crawcin())
  360.           {
  361.             case 'H' & 037:        /* BACKSPACE */
  362.             case 0177:
  363.                 if ( i > 0 ) 
  364.                 {
  365.                     i--;
  366.                     cmd[i] = 0;
  367.                     if(echo) pop_printf("\010 \010");
  368.                 }
  369.                 else
  370.                     Crawio(7);
  371.                 break;
  372.             
  373.             case '\r':
  374.                 pop_printf("\r\n");
  375.                 c = '\n';
  376.             case 'Z' & 037:    /* CONTROL-Z , exit */
  377.             case 'C' & 037:    /* CONTROL-C , exit */
  378.                 return((int)c);                        
  379.         
  380.             default:
  381.                 if((i >= len || (c < ' ') || (c > '~')))
  382.                 {
  383.                     Crawio('\a');
  384.                     break;
  385.                 }
  386.                 cmd[i++] = c;
  387.                 cmd[i] = 0;
  388.                 if(echo) Crawio(c);
  389.                 break;
  390.           }
  391.           tcp_stat(0,NULL);
  392.       }
  393.       return(0);
  394. }
  395.  
  396.  
  397. int pop_dispatch(int s,char *pop_userstr)
  398. {
  399. int argc;
  400. char *argv[30];
  401. register pop_cmd *p;
  402.  
  403.     argc = pop_args(pop_userstr,argv);
  404.     if(!argc) return(TRUE);
  405.       if(argc == 1 && atoi(argv[0]) > 0)
  406.     {
  407.           argv[1] = argv[0];
  408.         argv[0] = "retr";
  409.           argc++;
  410.     }
  411.     for(p=cmd_tab; p->cmd; p++)
  412.     {
  413.         if(!stricmp(p->cmd,argv[0]) && p->pop_fn)
  414.         {
  415.             return(p->pop_fn(s,argc,argv));
  416.         }
  417.     }
  418.     pop_printf("ERR - unknown command \"%s\"\r\n",argv[0]);
  419.     return(TRUE);        /* stay in loop */
  420. }
  421.  
  422. int pop_dummy(int s,int argc, char *argv[])
  423. {
  424.     if(s<0 || !argc || !argv) return(TRUE);
  425.     return(FALSE);        /* exit loop */
  426. }
  427.  
  428. int pop_stat(int s,int argc, char *argv[])
  429. {
  430.     nputl(s,argv[0]);
  431.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  432.     {
  433.         argc = pop_args(pop_userstr,argv);
  434.         if(argc != 3)
  435.             pop_printf("ERR crazy reply on stat cmd\r\n");
  436.         else
  437.             pop_printf("%s has %s message(s) (%s octets).\r\n",username,argv[1],argv[2]);
  438.     }
  439.     return(TRUE);        /* stay in loop */
  440. }
  441.  
  442.  
  443. int pop_exit(int s,int argc, char *argv[])
  444. {
  445.     if(!argc || !argv) return(FALSE);
  446.     nputl(s,"rset");
  447.     if(!pop_getresponse(s,pop_userstr,sizeof(pop_userstr)-1,FALSE))
  448.     {
  449.         pop_printf("%s\r\n",&pop_userstr[1]);
  450.         return(TRUE);    /* error: stay in loop */
  451.     }
  452.     return(FALSE);        /* exit loop */
  453. }
  454.  
  455.  
  456. int pop_rset(int s,int argc, char *argv[])
  457. {
  458.     if(!argc) return(TRUE);
  459.     nputl(s,argv[0]);
  460.     pop_getresponse(s,pop_userstr,sizeof(pop_userstr)-1,TRUE);
  461.     return(TRUE);        /* stay in loop */
  462. }
  463.  
  464.  
  465.  
  466. int pop_del(int s, int argc, char *argv[])
  467. {
  468. struct msg_list
  469. {
  470.     int        nr;
  471.     size_t    size;
  472. } *msg;
  473. int    i,cnt,j,k,max;
  474. char buf[80];
  475.  
  476.     if(argc == 1)
  477.     {
  478.         pop_dispatch(s,"help del");
  479.         return(TRUE);
  480.     }
  481.     buf[0]=0;
  482.     if(argc == 2 && !strchr(argv[1],'-') && !strchr(argv[1],','))
  483.     {                /* delete a single message */
  484.         nprintf(s,"dele %s\r\n",argv[1]);
  485.         pop_getresponse(s,pop_userstr,sizeof(pop_userstr),TRUE);
  486.         return(TRUE);
  487.     }
  488.     for(i=1;i<argc; i++)    /* save range info */
  489.     {
  490.         strcat(buf,argv[i]);
  491.         strcat(buf," ");
  492.     }
  493.     max = 0;
  494.     nputl(s,"list");
  495.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  496.     {
  497.         pop_args(pop_userstr,argv);
  498.         cnt = atoi(argv[1]);
  499.         if(!cnt)
  500.         {
  501.             pop_printf("%s has no messages\r\n",username);
  502.             ngets(s,pop_userstr,sizeof(pop_userstr));
  503.             return(TRUE);
  504.         }
  505.         msg = (struct msg_list *)malloc(sizeof(struct msg_list)*(size_t)cnt);
  506.         i=0;
  507.         do        /* build up msg list */
  508.         {
  509.             if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  510.             {
  511.                 free(msg);
  512.                 return(FALSE);
  513.             }
  514.             if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  515.                 break;
  516.             pop_args(pop_userstr,argv);
  517.             msg[i].nr = atoi(argv[0]);
  518.             if(msg[i].nr > max) max = msg[i].nr;
  519.             i++;
  520.         } while(1);
  521.         i = range_next(buf,max);
  522.         k = 0;
  523.         while(i>0)
  524.         {
  525.             for(j=0; j<cnt; j++)
  526.             {
  527.                 if(msg[j].nr == i)
  528.                 {
  529.                     nprintf(s,"dele %d\r\n",i);
  530.                     if(!pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  531.                     {
  532.                         free(msg);
  533.                         pop_printf("%s\r\n",&pop_userstr[1]);
  534.                         return(TRUE);
  535.                     }
  536.                     msg[j].nr = 0;
  537.                     k++;
  538.                 }
  539.             }
  540.             i = range_next(NULL,max);
  541.         }
  542.         pop_printf("%d message(s) deleted.\r\n",k); 
  543.         free(msg);    
  544.     }
  545.     return(TRUE);
  546. }
  547.  
  548. int pop_mget(int s, int argc, char *argv[])
  549. {
  550. struct msg_list
  551. {
  552.     int        nr;
  553.     size_t    size;
  554. } *msg;
  555. int    i,cnt,j,k,max;
  556. char buf[80];
  557. char *p;
  558. int c;
  559.  
  560.     if(argc <3)
  561.     {
  562.         pop_dispatch(s,"help ");
  563.         return(TRUE);
  564.     }
  565.     strcpy(pop_mailfile,argv[argc-1]);
  566.     buf[0]=0;
  567.     p = strchr(pop_mailfile,'.');
  568.     if(p) *p=0;
  569.     else if(!p) 
  570.     {
  571.         p=strrchr(pop_mailfile,'\\');    /* find last \ */
  572.         if(!p) p = strchr(pop_mailfile,':');
  573.         if(!p) p = pop_mailfile;
  574.         p[7]=0;        /* cut off extension */
  575.     }
  576.     for(i=1;i<argc-1; i++)    /* save range info */
  577.     {
  578.         strcat(buf,argv[i]);
  579.         strcat(buf," ");
  580.     }
  581.     max = 0;
  582.     nputl(s,"list");
  583.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  584.     {
  585.         pop_args(pop_userstr,argv);
  586.         cnt = atoi(argv[1]);
  587.         if(!cnt)
  588.         {
  589.             pop_printf("%s has no messages\r\n",username);
  590.             ngets(s,pop_userstr,sizeof(pop_userstr));
  591.             return(TRUE);
  592.         }
  593.         msg = (struct msg_list *)malloc(sizeof(struct msg_list)*(size_t)cnt);
  594.         i=0;
  595.         do        /* build up msg list */
  596.         {
  597.             if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  598.             {
  599.                 free(msg);
  600.                 return(FALSE);
  601.             }
  602.             if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  603.                 break;
  604.             pop_args(pop_userstr,argv);
  605.             msg[i].nr = atoi(argv[0]);
  606.             if(msg[i].nr > max) max = msg[i].nr;
  607.             i++;
  608.         } while(1);
  609.         i = range_next(buf,max);
  610.         k = 0;
  611.         while(i>0)
  612.         {
  613.             if(Cconis())
  614.             {
  615.                 c = (int)Crawcin();
  616.                 if(c == ('C' & 037))
  617.                   break;
  618.             }
  619.             for(j=0; j<cnt; j++)
  620.             {
  621.                 if(msg[j].nr == i)
  622.                 {
  623.                     sprintf(pop_userstr,"get %d %s.%03d",i,pop_mailfile,i);
  624.                     pop_dispatch(s,pop_userstr);
  625.                     if(!pop_getok)
  626.                     {
  627.                         free(msg);
  628.                         return(TRUE);
  629.                     }
  630.                     msg[j].nr = 0;
  631.                     k++;
  632.                 }
  633.             }
  634.             i = range_next(NULL,max);
  635.         }
  636.         pop_printf("%d message(s) copied.\r\n",k); 
  637.         free(msg);    
  638.     }
  639.     return(TRUE);
  640. }
  641.  
  642.  
  643. int pop_list(int s,int argc, char *argv[])
  644. {
  645. struct msg_list
  646. {
  647.     int        nr;
  648.     size_t    size;
  649. } *msg;
  650. int    i,cnt,j,k;
  651. char c;
  652. char weekday[80];
  653. int  day;
  654. char month[20];
  655. int  year;
  656. int  hour,minute;
  657. FILE *file = NULL;
  658.  
  659.  
  660.     if(!argc) return(TRUE);
  661.     if(argc == 2)
  662.     {
  663.         file = fopen(argv[1],"wb");
  664.         if(!file)
  665.         {
  666.             pop_printf("cannot open '%s'\r\n",argv[1]);
  667.             return(TRUE);
  668.         }
  669.     }
  670.     nputl(s,"list");
  671.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  672.     {
  673.         pop_args(pop_userstr,argv);
  674.         cnt = atoi(argv[1]);
  675.         if(!cnt)
  676.         {
  677.             pop_printf("%s has no messages\r\n",username);
  678.             ngets(s,pop_userstr,sizeof(pop_userstr));
  679.             return(TRUE);
  680.         }
  681.         msg = (struct msg_list *)malloc(sizeof(struct msg_list)*(size_t)cnt);
  682.         i=0;
  683.         for(i=0;i<cnt;i++)        /* build up msg list */
  684.         {
  685.             if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  686.             {
  687.                 free(msg);
  688.                 return(TRUE);
  689.             }
  690.             if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  691.                 break;
  692.             pop_args(pop_userstr,argv);
  693.             msg[i].nr = atoi(argv[0]);
  694.             msg[i].size = atol(argv[1]);
  695.         }
  696.         k=0;
  697.         for(i=0; i<cnt; i++)
  698.         {
  699.             if(!file && (++k == 25))    
  700.             {
  701.                 pop_printf(MORE);
  702.                 while(!Cconis()) tcp_stat(0,NULL);
  703.                 c = (char)Crawcin();
  704.                 if( c == ('C' & 037) || c=='q' || c=='Q')
  705.                 {
  706.                     free(msg);
  707.                     return(TRUE);
  708.                 }
  709.                 k--;
  710.                 pop_printf("\r         \r");
  711.                 if(c == ' ') k=0;
  712.             }
  713.             if(!file && Cconis()) switch(c = (char)Crawcin())
  714.             {
  715.                 case 'S' & 037:
  716.                     do
  717.                     {
  718.                         while(!Cconis()) tcp_stat(0,NULL);
  719.                         c = (char)Crawcin();
  720.                         if( c == ('C' & 037))
  721.                         {
  722.                             free(msg);
  723.                             return(TRUE);
  724.                         }
  725.                     }while(c != ('Q' & 037) && 
  726.                            c != ' ');
  727.                     break;
  728.                     
  729.                 case 'C' & 037:
  730.                     free(msg);
  731.                     return(TRUE);
  732.                 
  733.             }
  734.             nprintf(s,"top %d 0\r\n",msg[i].nr);
  735.             pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE);
  736.  
  737.             pop_linedate[0]=0;    /* clear strings */
  738.             pop_linesubj[0]=0;
  739.             pop_linefrom[0]=0;
  740.             pop_linestat[0]=0;
  741.             do        /* parse msg header */
  742.             {
  743.                 pop_userstr[0] = '\0';
  744.                 if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  745.                 {
  746.                     free(msg);
  747.                     pop_printf("error in parsing header\r\n");
  748.                     break;
  749.                 }
  750.                 if(strlen(pop_userstr)>=2 && 
  751.                    pop_userstr[strlen(pop_userstr)-2] == '\r')
  752.                     pop_userstr[strlen(pop_userstr)-2] = '\0';                
  753.                 if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  754.                     break;
  755.                   if(!strncmp((char *)pop_userstr,"Date:",5))
  756.                 {
  757.                     if(sscanf(pop_userstr,"%[^0-9]%d %[A-Za-z]%d %d:%d:",weekday,&day,month,&year,&hour,&minute) != 6)
  758.                     {
  759.                         j=5;
  760.                           while(pop_userstr[j++] != ','); /* find start of date */
  761.                         strncpy(pop_linedate,(char *)&pop_userstr[j],15);
  762.                     }
  763.                     else
  764.                     {
  765.                         if(year > 100) year %= 100;
  766.                         sprintf(pop_linedate,"%2d %-3.3s %2d,%2d:%2d",day,month,year,hour,minute);
  767.                     }
  768.                   }
  769.                 if(!strncmp((char *)pop_userstr,"From:",5))
  770.                 {
  771.                     j = 5;
  772.                     while(pop_userstr[j] == ' ') j++; /* find first nonblank char */
  773.                     strncpy(pop_linefrom,(char *)&pop_userstr[j],20); 
  774.                 }
  775.                 if(!strncmp((char *)pop_userstr,"Subject:",8))
  776.                 {
  777.                     j = 8;
  778.                     while(pop_userstr[j] == ' ') j++; /* find first nonblank char */
  779.                     strncpy(pop_linesubj,(char *)&pop_userstr[j],27); 
  780.                 }
  781.                 if(!strncmp((char *)pop_userstr,"Status:",7)) 
  782.                 {
  783.                     if(strchr((char *)pop_userstr,'U')) strcpy(pop_linestat," N");
  784.                     else strcpy(pop_linestat,"  ");
  785.                 }
  786.             } while(1);
  787.               if(i<cnt)
  788.               {
  789.                 if(!file)
  790.                   pop_printf("%2.2s%3d %-20.20s %-15.15s %8ld %-27.27s\r\n",pop_linestat,msg[i].nr,pop_linefrom,pop_linedate,msg[i].size,pop_linesubj);
  791.                 else
  792.                   fprintf(file,"%2.2s%3d %-20.20s %-15.15s %8ld %-27.27s\r\n",pop_linestat,msg[i].nr,pop_linefrom,pop_linedate,msg[i].size,pop_linesubj);
  793.               }
  794.         }
  795.         if(file) fclose(file);
  796.         free(msg);
  797.         return(TRUE);
  798.     }
  799.     if(file) fclose(file);
  800.     pop_printf("internal error\r\n");
  801.     return(FALSE);
  802. }
  803.  
  804.  
  805. int pop_retr(int s,int argc, char *argv[])
  806. {
  807. int i;
  808. char c;
  809.     if(argc < 2)
  810.     {
  811.         pop_dispatch(s,"help retr");
  812.         return(TRUE);
  813.     }
  814.     nprintf(s,"%s %s\r\n",argv[0],argv[1]);
  815.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),TRUE))
  816.     {
  817.         i=0;
  818.         do
  819.         {
  820.             if(i >= 0 && ++i >= 24)    
  821.             {
  822.                 pop_printf(MORE);
  823.                 while(!Cconis()) tcp_stat(0,NULL);
  824.                 c = (char)Crawcin();
  825.                 pop_printf("\r         \r");
  826.                 if(c == ('C' & 037) || (c == 'Q') || (c == 'q'))
  827.                 {
  828.                     i = -1;
  829.                     pop_printf("\rskipping message...\r");
  830.                 }
  831.                 i--;
  832.                 if(c == ' ') i=0;
  833.             }
  834.             if(Cconis())
  835.             switch(c = (char)Crawcin())
  836.             {
  837.                 case 'S' & 037:
  838.                     do
  839.                     {
  840.                         while(!Cconis()) tcp_stat(0,NULL);
  841.                         c = (char)Crawcin();
  842.                         if( c == ('C' & 037))
  843.                         {
  844.                             pop_printf("\rskipping message...\r");
  845.                             i = -1;
  846.                             break;
  847.                         }
  848.                     }while(c != ('Q' & 037) && c != ' ');
  849.                     break;
  850.                     
  851.                 case 'C' & 037:
  852.                     pop_printf("\rskipping message...\r");
  853.                     i = -1;
  854.                     break;
  855.                 
  856.             }
  857.             if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  858.                 return(FALSE);
  859.             if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  860.                 break;
  861.             if(i>=0)
  862.                 if(pop_userstr[0] == '.')
  863.                 {
  864.                     i += ((int)strlen(pop_userstr)-1) / 80;
  865.                     pop_printf("%s\r\n",&pop_userstr[1]);
  866.                 }
  867.                 else
  868.                 {
  869.                     i += (int)strlen(pop_userstr) / 80;
  870.                     pop_printf("%s\r\n",pop_userstr);
  871.                 }
  872.         } while(1);
  873.     }
  874.     pop_printf("\r                      \r");
  875.     return(TRUE);
  876. }
  877.  
  878.  
  879. int pop_get(int s,int argc, char *argv[])
  880. {
  881. FILE *fp;
  882. char buf[60];
  883. int i;
  884. long t;
  885.  
  886.     if(argc == 1)
  887.     {
  888.         pop_dispatch(s,"help get");
  889.         return(TRUE);
  890.     }
  891.     if(argc < 3)
  892.     {
  893.         if(pop_getcmd("Filename: ",buf,60,TRUE) != '\n')
  894.             return(TRUE);
  895.         argv[2] = buf;
  896.     }
  897.     pop_printf("%s: ",argv[2]);
  898.     if((fp = fopen(argv[2],"w"))==NULL)
  899.     {
  900.         pop_printf("ERR cannot open \r\n");
  901.         pop_getok = FALSE;
  902.         return(TRUE);
  903.     }
  904.     nprintf(s,"retr %s\r\n",argv[1]);
  905.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),TRUE))
  906.     {
  907.         i=0;
  908.         t = clock()+100;
  909.         do
  910.         {
  911.             if(clock() > t+10)
  912.             {
  913.                 pop_printf("%c\r","-\\|/"[i++ & 3]);
  914.                 t = clock();
  915.             }
  916.             if(!ngets(s,pop_userstr,sizeof(pop_userstr)))
  917.             {
  918.                 fclose(fp);
  919.                 return(FALSE);
  920.             }
  921.             if(pop_userstr[0] == '.' && pop_userstr[1] != '.')
  922.                 break;
  923.             if(pop_userstr[0] == '.')
  924.             {
  925.                 if(fprintf(fp,"%s\n",&pop_userstr[1])== EOF)
  926.                     goto write_err;
  927.             }
  928.             else
  929.             {
  930.                 if(fprintf(fp,"%s\n",pop_userstr)== EOF)
  931.                     goto write_err;
  932.             }
  933.         } while(1);
  934.         fclose(fp);
  935.         pop_getok = TRUE;
  936.         return(TRUE);
  937.     }
  938. write_err:
  939.     pop_printf("ERR cannot write file\r\n");
  940.     fclose(fp);
  941.     unlink(argv[2]);
  942.     pop_getok = FALSE;
  943.     return(TRUE);
  944. }
  945.  
  946. int pop_alias(int s,int argc, char *argv[])
  947. {
  948. int    i;
  949.     if(argc == 1)
  950.     {
  951.         pop_dispatch(s,"help alias");
  952.         return(TRUE);
  953.     }
  954.     i = lookup_alias(username,argv[1],pop_mailto,sizeof(pop_mailto)-1);
  955.     if(i < 0)
  956.     {
  957.         pop_printf("alias exceeds bufferspace\r\n");
  958.         return(TRUE);
  959.     }
  960.     if(!i)
  961.         pop_printf("\"%s\" is not aliased\r\n",pop_mailto);
  962.     else
  963.         pop_printf("%s\r\n",pop_mailto);
  964.     return(TRUE);
  965. }
  966.  
  967. int pop_cd(int s, int argc, char *argv[])
  968. {
  969. int disk = 0,olddisk;
  970.     if(argc > 1 && s>=0)
  971.     {
  972.         olddisk = Dgetdrv();
  973.         if(argv[1][1]==':')
  974.         {
  975.             disk = (argv[1][0] & ~0x20) - 'A';
  976.             if(disk<0 || disk > 15 || Dsetdrv(disk)<0L)
  977.             {
  978.                 pop_printf("invalid drive \"%c\"\r\n",argv[1][0]);
  979.                 return(TRUE);
  980.             }    
  981.             argv[1] += 2;
  982.         }
  983.         if(argv[1][0] &&  Dsetpath(argv[1])<0)
  984.         {
  985.             pop_printf("cannot chdir to \"%s\"\r\n",argv[1]);
  986.             Dsetdrv(olddisk);
  987.         }
  988.     }
  989.     getcwd(pop_userstr,(int)sizeof(pop_userstr));
  990.     pop_printf("%s\r\n",pop_userstr);
  991.     return(TRUE);
  992. }
  993.  
  994. int pop_mail(int s,int argc, char *argv[])
  995. {
  996. FILE *fp;
  997. int  c;
  998. int  cr;
  999.  
  1000.     if(argc == 1)
  1001.     {
  1002.         if(pop_getcmd("To: ",pop_mailto,sizeof(pop_mailto),TRUE) != '\n')
  1003.             return(TRUE);
  1004.         argv[1] = pop_mailto;
  1005.     }
  1006.     if(lookup_alias(username,argv[1],pop_mailto,sizeof(pop_mailto)-1) < 0)
  1007.     {
  1008.         pop_printf("alias excceds bufferspace\r\n");
  1009.         return(TRUE);
  1010.     }
  1011.     if(pop_getcmd("Subject: ",pop_mailsubj,sizeof(pop_mailsubj),TRUE) != '\n')
  1012.         return(TRUE);
  1013.     if(argc < 3)
  1014.     {
  1015.         if(!tmpnam(pop_mailfile))
  1016.             return(TRUE);
  1017.         argv[2] = pop_mailfile;
  1018.         if((fp = fopen(argv[2],"w"))==NULL)
  1019.         {
  1020.             pop_printf("cannot open tempfile\r\n");
  1021.             return(TRUE);
  1022.         }
  1023.         pop_printf("Type in message, end with CTRL-Z or a sigle dot, abort with CTRL-C\r\n");
  1024.         do    /* get message */
  1025.         {
  1026.             c = pop_getcmd(">",pop_userstr,sizeof(pop_userstr),TRUE);
  1027.             if(c == ('C' & 037))
  1028.             {
  1029.                 pop_printf("\r\nmessage not sent\r\n");
  1030.                 fclose(fp);
  1031.                 unlink(argv[2]);
  1032.                 return(TRUE);
  1033.             }
  1034.             if(!strcmp(pop_userstr,"."))
  1035.             {
  1036.                 pop_printf("[EOT]\r\n");
  1037.                 fclose(fp);
  1038.                 break;
  1039.             }
  1040.             fprintf(fp,"%s\n",pop_userstr);
  1041.             if(c == ('Z' & 037))
  1042.             {
  1043.                 pop_printf("[EOT]\r\n");
  1044.                 fclose(fp);
  1045.                 break;
  1046.             }
  1047.         }while(1);
  1048.     }
  1049.     if((fp = fopen(argv[2],"rb"))==NULL)
  1050.     {
  1051.         pop_printf("cannot open \"%s\"\r\n",argv[2]);
  1052.         return(TRUE);
  1053.     }
  1054.     nprintf(s,"xtnd xmit\r\n");
  1055.     if(pop_getresponse(s,pop_userstr,sizeof(pop_userstr),FALSE))
  1056.     {
  1057.         nprintf(s,"From: %s\r\n",username);
  1058.         nprintf(s,"To: %s\r\n",pop_mailto);
  1059.         nprintf(s,"Subject: %s\r\n",pop_mailsubj);
  1060.         cr=FALSE;
  1061.         do
  1062.         {
  1063.             if(!fgets(pop_userstr,(int)sizeof(pop_userstr),fp) ||
  1064.                !strcmp(pop_userstr,".\r\n"))
  1065.             {
  1066.                 if(!strcmp(pop_userstr,".\r\n"))
  1067.                 {
  1068.                     pop_printf("WARNING: message contains a single dot in a line\r\n"
  1069.                                "message not entirely sent\r\n");
  1070.                 }
  1071.                 if(!cr) nputs(s,"\r\n");
  1072.                 nputl(s,".");
  1073.                 break;
  1074.             }
  1075. #ifdef STUFF
  1076.             if(pop_userstr[0] == '.')    /* do byte stuffing */
  1077.                 nputc(s,'.');
  1078. #endif
  1079.             nputs(s,pop_userstr);
  1080.             cr = (pop_userstr[strlen(pop_userstr)-1]=='\n');
  1081.         } while(1);
  1082.         pop_getresponse(s,pop_userstr,sizeof(pop_userstr),BEE);
  1083.         fclose(fp);
  1084.         if(argc < 3) unlink(argv[2]);
  1085.         return(TRUE);
  1086.     }
  1087.     pop_printf("%s\r\n",&pop_userstr[1]);
  1088.     if(argc < 3) unlink(argv[2]);
  1089.     fclose(fp);
  1090.     return(TRUE);
  1091. }
  1092.  
  1093.  
  1094.  
  1095. int pop_help(int s,int argc, char *argv[])
  1096. {
  1097. int i = 0;
  1098.     if(s<0) return(TRUE);
  1099.     if(argc == 1)
  1100.     {
  1101.         for(i=0; cmd_tab[i].cmd; )
  1102.         {
  1103.             pop_printf("\t%s",cmd_tab[i].cmd);
  1104.             if((++i % 5) == 4) pop_printf("\r\n");
  1105.         }
  1106.         if((i % 5) != 4) pop_printf("\r\n");
  1107.         return(TRUE);
  1108.     };
  1109.  
  1110.     for(i=0; cmd_tab[i].cmd; i++)
  1111.     {
  1112.         if(!strnicmp(cmd_tab[i].cmd,argv[1],strlen(argv[1])))
  1113.             pop_printf("    %s\r\n",cmd_tab[i].help);
  1114.     }
  1115.     return(TRUE);        /* stay in loop */
  1116. }
  1117.  
  1118. static char ppf_buf[4096];        /* take care, do not exceed */
  1119.  
  1120. int pop_printf(char *str,...)
  1121. {
  1122. va_list    args;
  1123. register int i,j;
  1124.  
  1125.     va_start(args,str);
  1126.     j = vsprintf(ppf_buf,str,args);        /* format string */
  1127.     va_end(args);
  1128.     if(j == EOF) return(EOF);
  1129.     for(i=0; i<j ;i++) Bconout(2,ppf_buf[i]);
  1130.     return(j);
  1131. }
  1132.  
  1133. static char netbuf[1024];
  1134. static int netbuf_rd = 0;
  1135. static int netbuf_size = 0;
  1136.  
  1137. int nconnect(char *host, unsigned int port)
  1138. {
  1139. DESTI dest;
  1140. int tcp_id;
  1141. long state;
  1142. TCPSTAT tstat;
  1143.  
  1144.   dest.Port = port;
  1145.   if(GetIPAddr(host,dest.IPAddr))
  1146.   {
  1147.     return(0);
  1148.   }
  1149.  
  1150.   tcp_id = (unsigned)tcp_open(0,&dest,AKTIV,60,POP_BUFFERSIZE);
  1151.  
  1152.   if(tcp_id <= 0)
  1153.   {
  1154.     return(-1);
  1155.   }
  1156.  
  1157.   do
  1158.   {
  1159.     state = (int)tcp_stat(tcp_id,&tstat);
  1160.     if((state > ESTABLISHED) || (state <= CLOSED)) break;
  1161.   }  while(state < ESTABLISHED);
  1162.  
  1163.   if(state != ESTABLISHED)
  1164.   {
  1165.     return(-2);
  1166.   }
  1167.   return(tcp_id);
  1168. }
  1169.  
  1170.  
  1171. int nprintf(int s, char *str,...)
  1172. {
  1173. va_list    args;
  1174. size_t    i,sent;
  1175. register int j;
  1176. int push;
  1177.  
  1178.     va_start(args,str);
  1179.     j = vsprintf(ppf_buf,str,args);        /* format string */
  1180.     va_end(args);
  1181.     if(j == EOF) return(EOF);
  1182.     push = (strchr(ppf_buf,'\n') != NULL) ? PUSH : NO_PUSH;
  1183.     for(i=0; i<j;)
  1184.     {
  1185.         sent = tcp_write(s,&ppf_buf[i],(int)(j-i),push,NO_URGENT);
  1186.         if(sent < 0) return((int)sent);
  1187.         
  1188.         if(pop_log && sent > 0) 
  1189.             fwrite(&str[i],sent,1,pop_log);
  1190.         i+=sent;
  1191.     }
  1192.     return(j);
  1193. }
  1194.  
  1195.  
  1196. int nputl(int s, char *str)
  1197. {
  1198. int len;
  1199.  
  1200.     len = nputs(s,str);
  1201.     if(len < 0) return(len);
  1202.     
  1203.     len += nputc(s,'\r');
  1204.     len += nputc(s,'\n');
  1205.     return(len);
  1206. }
  1207.  
  1208. int nputs(int s, char *str)
  1209. {
  1210. size_t    length,i,sent;
  1211.  
  1212.     length = strlen(str);
  1213.     for(i=0; i<length;)
  1214.     {
  1215.         sent = tcp_write(s,&str[i],(int)(length-i),NO_PUSH,NO_URGENT);
  1216.         if(sent < 0) return((int)sent);
  1217.         
  1218.         if(pop_log && sent > 0) 
  1219.             fwrite(&str[i],sent,1,pop_log);
  1220.         i+=sent;
  1221.     }
  1222.     return((int)length);
  1223. }
  1224.  
  1225. int nputc(int s, char c)
  1226. {
  1227. long cnt;
  1228.  
  1229.     while((cnt = tcp_write(s,&c,1,c=='\n' ? PUSH : NO_PUSH,NO_URGENT)) == 0);
  1230.     if(cnt != 1) return((int)cnt);
  1231.     if(pop_log) fputc(c,pop_log);
  1232.     return(1);
  1233. }
  1234.  
  1235.  
  1236. char *ngets(int s, char *buf,size_t len)
  1237. {
  1238. register int i;
  1239. register char *p;
  1240. register int newline = 0;
  1241. TCPSTAT tstat;
  1242.  
  1243.   if(s < 0) return(NULL);
  1244.   p=buf;
  1245.   *p = 0;
  1246.   tcp_stat(s,&tstat);
  1247.   while(len>0)
  1248.   {
  1249.     if(netbuf_size == 0)
  1250.     {
  1251.         netbuf_rd = 0;
  1252.         do
  1253.         {
  1254.               netbuf_size = (int)tcp_read(s,netbuf,(int)sizeof(netbuf)-1);
  1255.               if(netbuf_size < 0)
  1256.               {
  1257.                   pop_connect = -1;
  1258.                   netbuf_size = 0;
  1259.                   return(NULL);
  1260.               }
  1261.         } while(netbuf_size == 0);
  1262.     }
  1263.     for(i=0;len && i < netbuf_size; i++)
  1264.     {
  1265.         len --;
  1266.         if(netbuf[netbuf_rd] == '\n')
  1267.         {
  1268.             p--;
  1269.             i++;
  1270.             newline++;
  1271.             netbuf_rd++;
  1272.             break;
  1273.         }
  1274.         else
  1275.             *p++ = netbuf[netbuf_rd];
  1276.         netbuf_rd++;
  1277.     }
  1278.     netbuf_size -= i;
  1279.     if(newline)
  1280.     {
  1281.         i-=2;
  1282.         break;
  1283.     }
  1284.   }
  1285.   *p = 0;
  1286.   if(pop_log) fwrite(buf,strlen(buf),1,pop_log);
  1287.   if(pop_log && newline) fprintf(pop_log,"\r\n");
  1288.   return(buf);
  1289. }
  1290.  
  1291. int ngetc(int s)
  1292. {
  1293.   
  1294.   if(s <= 0) return(EOF);
  1295.   
  1296.   if(netbuf_size > 0)
  1297.   {
  1298.       netbuf_size--;
  1299.       return((int)netbuf[netbuf_rd++]);
  1300.   }
  1301.   netbuf_rd = 0;
  1302.   do
  1303.   {
  1304.     netbuf_size = (int)tcp_read(s,netbuf,(int)sizeof(netbuf));
  1305.   } while( netbuf_size == 0);
  1306.   if(netbuf_size < 0)
  1307.   {
  1308.       pop_connect = -1;
  1309.       return(EOF);
  1310.   }
  1311.   netbuf_size--;
  1312.   return((int)netbuf[netbuf_rd++]);
  1313. }
  1314.  
  1315. int navail(int s)
  1316. {
  1317.     if(netbuf_size) return(netbuf_size);
  1318.     netbuf_rd = 0;
  1319.     netbuf_size = (int)tcp_read(s,netbuf,(int)sizeof(netbuf));
  1320.     return(netbuf_size);
  1321. }